//! 应用生命周期及上下文管理

use std::sync::Arc;

use axum::{middleware::from_extractor, Router, routing::{get, post}, Json, Extension};
use axum_sqlite::Database;
use dotenv::dotenv;

use state::Container;
use tracing::info;

use crate::{config::Config, handler::{helper, auth}, middleware::authed::Authed, form::{EmptyVo, AdminLogin}, model::AppState};


pub static APP_CONTEXT: Container![Send + Sync] = <Container![Send + Sync]>::new();

///应用配置
pub fn config(){

    // RUST_LOG=trace cargo run
    if std::env::var_os("RUST_LOG").is_none() {
        std::env::set_var("RUST_LOG", "axum_side=trace");
    }

    tracing_subscriber::fmt::init();

    dotenv().ok();

    let cfg = Config::from_env().unwrap();
    
    info!("config is:{:?}", cfg);

    set_config(cfg);
}

#[inline]
pub fn set_config<T: Send + Sync + 'static>(state: T) -> bool {
    APP_CONTEXT.set(state)
}

#[inline]
pub fn set_db<T: Send + Sync + 'static>(db: T) -> bool {
    APP_CONTEXT.set(db)
}

#[inline]
pub fn get_config<T: 'static>() -> &'static T {
    APP_CONTEXT.get()
}

#[inline]
pub fn get_db<T: 'static>() -> &'static T {
    APP_CONTEXT.get()
}

#[inline]
pub fn set_state<T: Send + Sync + 'static>(state: T) -> bool {
    APP_CONTEXT.set(state)
}

#[inline]
pub fn get_state<T: 'static>() -> &'static T {
    APP_CONTEXT.get()
}

/// 初始化
pub fn init(){
    // 初始化数据库
    init_db();

    // let rdc = redis::Client::open(cfg.redis.dsn).unwrap();
    // tracing::info!("Web服务监听于{}", &cfg.web.addr);
}

fn get_init_sql()->String{
    String::from(r#"
    BEGIN;
    CREATE TABLE admin (
        id SERIAL PRIMARY KEY,
        username VARCHAR(50) NOT NULL,
        password VARCHAR(255) NOT NULL,
        is_sys BOOLEAN NOT NULL DEFAULT FALSE,
        is_del BOOLEAN NOT NULL DEFAULT FALSE,
        UNIQUE(username)
    );
    INSERT INTO admin(id, username, password, is_sys, is_del) VALUES(1, 'admin', '$2b$12$DWdD4usqXfhacmbYD0aJxe1F0tD7fpNupdz3onNSW21kMu/V7yrme', true, false);
    COMMIT;
    "#)
}

fn init_db(){
    let db = Database::new(":memory:").unwrap();
    set_db::<Extension<Database>>(db);

    let Extension(pool): Extension<Database> = get_db::<Extension<Database>>().clone();

    let connection = pool.connection().unwrap();
    
    connection.execute_batch(get_init_sql().as_str());
    // println!("init db data: {}", );
}

///
/// 路由注册
/// 
pub fn routers() -> Router {
    // 身份校验api
    let auth_router = Router::new().route("/userinfo", get(||async {helper::render(Some(EmptyVo{}), String::from("登录信息"),auth::userinfo)}))
    .layer(from_extractor::<Authed>());

    // app 路由
    let app_router = Router::new()
    .nest("/api", auth_router)
    .route("/api/login", post(|Json(payload): Json<AdminLogin>|async {helper::render(Some(payload),String::from("登录"),auth::login)}));

    app_router
}